package server;

import control.CControl;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Observable;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SNewConnectionsHandler extends Observable implements Runnable
{
    private final static Logger LOGGER = Logger.getLogger(SNewConnectionsHandler.class
        .getName());
    
    private int port;
    private volatile Boolean runServer = Boolean.FALSE;
    private static final int socketTimeout = 3000;
    private CControl cControl;
    
    public static final String STATUS_RUNNING = "Running";
    public static final String STATUS_STOPPED = "Stopped";
    
    public SNewConnectionsHandler(CControl cControl)
    {
        if(cControl == null){
            throw new IllegalArgumentException("cControl is null");
        }
        
        this.cControl = cControl;
    }

    public void startServer(int port)
    {
        if (port < 1 || port > 65536)
        {
            throw new IllegalArgumentException(port + " is not a correct port number");
        }
        
        if (this.runServer == Boolean.FALSE)
        {
            this.port = port;
            this.runServer = Boolean.TRUE;
            new Thread(this).start();
        }
    }
    
    public void stopServer()
    {
        LOGGER.info("Stopping Connection Handler server..");
        this.runServer = Boolean.FALSE;
    }
    
    @Override
    public void run()
    {
        LOGGER.info("Connection Handler server is running. Waiting for connections..");
        
        ServerSocket serverSocket = null;
        Socket clientSocket = null;
        
        try
        {
            serverSocket = new ServerSocket(port);
            serverSocket.setSoTimeout(socketTimeout); // Set timeout to one second, so that each second the this.runServer value will be checked
            setChanged();
            notifyObservers(STATUS_RUNNING);
            
            while (this.runServer)
            {
                // Accept incoming connection and run a thread to process it
                try
                {
                    clientSocket = serverSocket.accept();
                    LOGGER.fine("New client was accepted");
                    // Pass client to request processor
                    new SRequestProcessor(cControl, clientSocket).start();
                }
                catch (SocketTimeoutException ex)
                {
                    // Do nothing, just check the runServer value and get back to the loop
                }
            }
            
            serverSocket.close();
            setChanged();
            notifyObservers(STATUS_STOPPED);
            LOGGER.info("Connection Handler server has been stopped manually");
        }
        catch (IOException e)
        {
           LOGGER.log(Level.SEVERE, "Connection Handler server was stopped because of IOException: {0}", e.getMessage());
           LOGGER.fine(e.toString());
           this.runServer = Boolean.FALSE;
           setChanged();
           notifyObservers(STATUS_STOPPED);
        }
    }
    
    
            
       
}
